#include "loginRegister.h"
#include <crypt.h>

int user_login(int sockfd)
{
    train_t train;
    memset(&train, 0, sizeof(train));
    train.type = CMD_SIGNIN; // 发送登录请求
    send(sockfd, &train.type, sizeof(train.type), MSG_NOSIGNAL);

    while (1)
    {
        char salt[21] = {0};
        char user_name[128] = {0};
        printf("用户名：");
        while (1)
        {
            memset(user_name, 0, sizeof(user_name));
            if (fgets(user_name, sizeof(user_name), stdin))
            {
                if (user_name[0] == '\n')
                {
                    printf("用户名为空！\n");
                }
                else
                {
                    user_name[strlen(user_name)-1]='\0';
                    break;
                }
            }
        }

        // 发送用户名
        memset(&train, 0, sizeof(train));
        train.length = strlen(user_name);
        memcpy(train.value, user_name, train.length);
        send(sockfd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
        send(sockfd, train.value, train.length, MSG_NOSIGNAL);

        memset(&train, 0, sizeof(train));
        recv(sockfd, &train.type, sizeof(train.type), MSG_WAITALL); // 接收服务端响应
        recv(sockfd, &train.length, sizeof(train.length), MSG_WAITALL);
        recv(sockfd, train.value, train.length, MSG_WAITALL);

        if (train.type == RESPON_OK) // 服务端返回盐值
        {
            strncpy(salt, train.value, sizeof(salt));
        }
        else if (train.type == RESPON_ERROR) // 用户名不存在
        {
            printf("error msg:%s\n", train.value);
            continue;
        }

        int wrong_pswd_count = 0; // 计算输错密码的次数
        while (1)
        {
            if(wrong_pswd_count == 3) // 输错3次
            {
                printf("密码错误次数过多！\n");
                train.type = -1;
                send(sockfd, &train.type, sizeof(train.type), MSG_NOSIGNAL);
                return -1;
            }
            memset(&train, 0, sizeof(train));
            char *passwd = getpass("请输入密码:");

            unsigned char encrypted_psw[32];
            unsigned int encrypted_len = 0;

            EVP_MD_CTX *ctx = EVP_MD_CTX_new();
            EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
            EVP_DigestUpdate(ctx, salt, strlen(salt));
            EVP_DigestUpdate(ctx, passwd, strlen(passwd));
            EVP_DigestFinal_ex(ctx, encrypted_psw, &encrypted_len);
            char psw_to_hex[65]; // 使用十六进制保存
            for (int i = 0; i < encrypted_len; i++)
            {
                sprintf(psw_to_hex + i * 2, "%02x", encrypted_psw[i]);
            }
            psw_to_hex[64] = '\0';
            EVP_MD_CTX_free(ctx);

            // 发送加密密码
            train.type = 0;
            train.length = strlen(psw_to_hex);
            memcpy(train.value, psw_to_hex, train.length);
            send(sockfd, &train.type, sizeof(train.type), MSG_NOSIGNAL);
            send(sockfd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
            send(sockfd, train.value, train.length, MSG_NOSIGNAL);

            memset(&train, 0, sizeof(train));
            recv(sockfd, &train.type, sizeof(train.type), MSG_WAITALL);
            recv(sockfd, &train.length, sizeof(train.length), MSG_WAITALL);
            recv(sockfd, train.value, train.length, MSG_WAITALL);
            if (train.type == RESPON_OK)
            {
                printf("%s\n", train.value);
                return 0;
            }
            else if(train.type == RESPON_ERROR)
            {
                printf("%s\n",train.value);
                wrong_pswd_count++;
                continue;
            }
        }
    }   
}

int user_register(int sockfd)
{
    train_t train;
    memset(&train, 0, sizeof(train));
    train.type = CMD_SIGNUP; // 发送注册请求
    send(sockfd, &train.type, sizeof(train.type), MSG_NOSIGNAL);

    // 用户输入用户名
    char user_name[128] = {0};
    while(1)
    {
        memset(user_name, 0, sizeof(user_name));
        printf("请输入用户名：\n");
        fgets(user_name, sizeof(user_name), stdin);
        user_name[strlen(user_name) - 1] = '\0';
        if (strlen(user_name) > 64)
        {
            printf("用户名不能超过64位。\n");
            continue;
        }
        else
        {
            break;
        }
    }

    //发送用户名
    train.length = strlen(user_name);
    send(sockfd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
    send(sockfd, user_name, train.length, MSG_NOSIGNAL);

    // 接收用户是否存在的确认
    memset(&train, 0, sizeof(train));
    recv(sockfd, &train.type, sizeof(train.type), MSG_WAITALL);
    recv(sockfd, &train.length, sizeof(train.length), MSG_WAITALL);
    recv(sockfd, train.value, train.length, MSG_WAITALL);
    if(train.type == RESPON_ERROR)
    {
        printf("%s\n",train.value);
        return -1;
    }
    else if(train.type == RESPON_OK)
    {}

    //接收盐值
    char salt[21] = {0};
    memset(&train, 0, sizeof(train));
    recv(sockfd, &train.length, sizeof(train.length), MSG_WAITALL);
    recv(sockfd, salt, train.length, MSG_WAITALL);

    // 发送加密密码
    char *passwd = getpass("请输入密码:");

    unsigned char encrypted_psw[32];
    unsigned int encrypted_len = 0;

    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
    EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
    EVP_DigestUpdate(ctx, salt, strlen(salt));
    EVP_DigestUpdate(ctx, passwd, strlen(passwd));
    EVP_DigestFinal_ex(ctx, encrypted_psw, &encrypted_len);
    char psw_to_hex[encrypted_len*2+1]; // 使用十六进制保存
    for (int i = 0; i < encrypted_len; i++)
    {
        sprintf(psw_to_hex + i * 2, "%02x", encrypted_psw[i]);
    }
    psw_to_hex[64] = '\0';
    EVP_MD_CTX_free(ctx);
    // 发送
    train.length = strlen(psw_to_hex);
    memcpy(train.value, psw_to_hex, train.length);
    send(sockfd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
    send(sockfd, train.value, train.length, MSG_NOSIGNAL);

    // 服务端接收确认
    recv(sockfd, &train.type, sizeof(train.type), MSG_WAITALL);
    if(train.type == RESPON_OK)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}